﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 设计模式.Decorator
{
    /// <summary>
    /// 源于晴阳兄的领域事件一讲
    /// 在Byteart Retail中，有一个特殊的领域事件处理器，它与其它领域事件处理器一样，
    /// 也继承于DomainEventHandler<TDomainEvent>泛型抽象类，但它的特殊性在于，它会在构造函数中接受一个Action<TDomainEvent>类型的委托作为参数，
    /// 于是，通过一种类似装饰器模式的方式，将Action<TDomainEvent>委托“装饰”成DomainEventHandler<TDomainEvent>类型的对象
    /// </summary>
    public interface IEventHandle<TEntiy> where TEntiy : IEvent
    {
        void Handle(IEvent msg);
    }

    public interface IEvent
    {
        public Guid ID { get { return Guid.NewGuid(); } }
    }

    public class TestEvent : IEvent
    {
        //新事件的属性
    }

    /// <summary>
    /// 标准领域事件处理
    /// </summary>
    public class TestEventHandle : IEventHandle<TestEvent>
    {
        public void Handle(IEvent msg)
        {
            Console.WriteLine("标准的领域事件处理程序" + msg.ID);
        }
    }

    #region 装饰器,适配器
    /// <summary>
    /// action<string>类型的处理程序，它允许你传入一个委托实例
    /// </summary>
    public class DomainDelegate<TEntity> : IEventHandle<TEntity> where TEntity : IEvent
    {

        Action<TEntity> _eventHandlerDelegate;
        public DomainDelegate(Action<TEntity> eventHandlerDelegate)
        {
            _eventHandlerDelegate = eventHandlerDelegate;
        }
        public void Handle(TEntity msg)
        {
            _eventHandlerDelegate(msg);
        }
    }

    #endregion

    public class DomainTest
    {
        private static List<object> eventHandlers = new List<object>();

        /// <summary>
        /// 处理
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="_events"></param>
        public void Process<TEntity>(IEventHandle<TEntity> _events) where TEntity : IEvent
        {
            eventHandlers.Add(_events);
        }
        public void Process<TEntity>(Action<TEntity> action) where TEntity : IEvent
        {
            Process(new DomainDelegate<TEntity>(action));
        }

        /// <summary>
        /// 激活
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="event"></param>
        public void Actived<TEntity>(TEntity @event) where TEntity : IEvent
        {
            foreach (var handler in eventHandlers)
            {
                var eventHandler = handler as IEventHandle<TEntity>;
                eventHandler.Handle(@event);
            }
        }
    }
}
